import sqlite3
import os
import logging


class Filter(object):
    def __init__(self, _field):
        self.field = _field

    def __and__(self, other):
        return Filter(self.field + " and " + other.field)

    def __or__(self, other):
        return Filter(self.field + " or " + other.field)

    def __ior__(self, other):
        return Filter(self.field + " or " + other.field)

    def __str__(self):
        print(self.field)
        return self.field


class Order(object):
    def __init__(self, field, asc=True):
        self.field = field
        self.asc = asc



def __or(left, right):
    return left | right


class Field(object):

    def __init__(self, name, column_type, primary_key=False, auto_inc=False):
        self.name = name
        self.column_type = column_type
        self.primary_key = primary_key
        self.auto_inc = auto_inc

    def __str__(self):
        return '<%s:%s>' % (self.__class__.__name__, self.name)


class Unique(object):
    def __init__(self, *fields):
        self.fields = fields


class TableInfo(type):
    def __new__(cls, name, base, attrs):
        """
        :param args: (类名，父类，会被继承下去的属性）
        :param kwargs: 空的
        """
        if name == "Table":
            return type.__new__(cls, name, base, attrs)
        mapping = dict()
        for att in attrs.items():
            if isinstance(att[1], Field):
                field_name, field = att
                mapping[field_name] = field
        for k in mapping.keys():
            attrs.pop(k)
        attrs['__mapping__'] = mapping
        attrs['__table__'] = name
        return type.__new__(cls, name, base, attrs)


class Table(dict, metaclass=TableInfo):

    def __init__(self, **kwargs):
        mapping = self.__mapping__
        for kw in kwargs.items():
            if kw[0] in mapping.keys():
                setattr(self, kw[0], kw[1])
        super(Table, self).__init__(kwargs)

    def __setitem__(self, key, value):
        # 绑定属性
        if key in self.__mapping__.keys():
            setattr(self, key, value)
        super(Table, self).__setitem__(key, value)


class User(Table):
    id = Field('id', "int")
    name = Field('name', 'varchar(30)')


class Stock(Table):
    code = Field('code', 'varchar(20)')
    market = Field('market', 'int')
    name = Field('name', 'varchar(40)')


class DBSession(object):

    def __init__(self):
        home_path = os.path.expanduser('~')
        stock_db_path = os.path.join(home_path, '.stock', 'db')
        if not os.path.exists(stock_db_path):
            os.makedirs(stock_db_path)
        self.conn = sqlite3.connect(os.path.join(stock_db_path, 'stock.db'))

    def create_table(self, info):
        sql = "CREATE TABLE IF NOT EXISTS %s("
        "code varchar(10) primary key,"
        "market int not null,"
        "name varchar(30) not null"
        ");"

    def save(self, record):
        record_cls = type(record)
        tableName = record_cls.__table__
        fields = record_cls.__mapping__
        fields = [field for field in fields.items() if hasattr(record, field[0]) and not (field[1].primary_key and field[1].auto_inc)]
        sql = "REPLACE INTO %s(%s) values (%s)" % (tableName, ",".join([field[1].name for field in fields]), ",".join(["?" for f in fields]))
        c = self.conn.cursor()
        values = tuple([record[field[0]] for field in fields])
        try:
            c.execute(sql, values)
            self.conn.commit()
        except Exception as e:
            logging.error('save error =>', exc_info=e)
            self.conn.rollback()

    def execute(self, info, sql, *args, fields=None):
        if isinstance(info, TableInfo):
            c = self.conn.cursor()
            if fields is None:
                # 获取元信息，更简单方式
                column_info = c.execute("""
                pragma table_info(%s);
                """ % info.__table__)
                fields = []
                for cc1 in column_info:
                    fields.append(cc1[1])
            sql_template = sql
            logging.debug('sql is => %s' % sql_template)
            cursor = c.execute(sql_template, args)

            for row in cursor:
                # 注意这里返回的是元组
                nex = info()
                for i in range(0, len(fields)):
                    nex[fields[i]] = row[i]
                yield nex
        else:
            return []

    def query(self, info, _filter=None, orders=None):
        """
        :param _filter: 过滤方式
        :param info: 表的类
        :return: 表对应元素列表
        """
        if isinstance(info, TableInfo):
            fields = [field.name for field in info.__mapping__.values()]
            fieldstr = ",".join([field.name for field in info.__mapping__.values()])
            sql_template = " ".join(["select", fieldstr, "from", info.__table__])
            if _filter is not None:
                sql_template = sql_template + " where " + str(_filter)
            if orders is not None:
                sql_template = sql_template + " order by "
                sql_template = sql_template + ",".join([order.field + (' desc' if not order.asc else '') for order in orders])
            return self.execute(info, sql_template, fields=fields)
        else:
            return []

    def close(self):
        self.conn.close()


if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    # dbSession = DBSession()
    # dbSession.save(record=Stock(name='中间123', code='129333', market=2))
    # dbSession.close()
    print(Filter('a=2') | (Filter('b=4')))

